home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / comms / non-internet / samba / source / vt_mode.c < prev    next >
C/C++ Source or Header  |  1996-06-26  |  8KB  |  497 lines

  1. /* vt_mode.c */
  2. /*
  3. support vtp-sessions
  4.  
  5. written by Christian A. Lademann <cal@zls.com>
  6. */
  7.  
  8. /*
  9. 02.05.95:cal:ported to samba-1.9.13
  10. */
  11.  
  12. #define    __vt_mode_c__
  13.  
  14.  
  15. /* #include    <stdio.h> */
  16. /* #include    <fcntl.h> */
  17. /* #include    <sys/types.h> */
  18. /* #include    <unistd.h> */
  19. /* #include    <signal.h> */
  20. /* #include    <errno.h> */
  21. /* #include    <ctype.h> */
  22. /* #include    <utmp.h> */
  23. /* #include    <sys/param.h> */
  24. /* #include    <sys/ioctl.h> */
  25. /* #include    <stdlib.h> */
  26. /* #include    <string.h> */
  27.  
  28. #include    "includes.h"
  29. #include    "vt_mode.h"
  30. #include    <utmp.h>
  31.  
  32. #ifdef SCO
  33.     extern char    *strdup();
  34. #endif
  35.  
  36. extern int Client;
  37.  
  38. #ifdef LINUX
  39. #    define    HAS_VTY
  40. #endif
  41.  
  42. #ifdef SCO
  43. #    define    HAS_PTY
  44. #    define    HAS_VTY
  45.  
  46. #    include    <sys/tty.h>
  47. #endif
  48.  
  49. extern int    DEBUGLEVEL;
  50. extern char    *InBuffer, *OutBuffer;
  51. extern int    done_become_user;
  52.  
  53. char    master_name [64], slave_name [64];
  54. int        master, slave, i, o, e;
  55.  
  56. int        ms_type = MS_NONE,
  57.         ms_poll = 0;
  58.  
  59.  
  60. /*
  61. VT_Check: test incoming packet for "vtp" or "iVT1\0"
  62. */
  63. int    VT_Check(buffer)
  64. char    *buffer;
  65. {
  66.     DEBUG(3,("Checking packet: <%10s...>\n", buffer+4));
  67.     if((strncmp(buffer+4, "vtp", 3) == 0 && smb_len(buffer) == 3) || (strncmp(buffer+4, "iVT1\0", 5) == 0 && smb_len(buffer) == 5))
  68.         return(1);
  69.     else
  70.         return(0);
  71. }
  72.  
  73.  
  74. /*
  75. VT_Start_utmp: prepare /etc/utmp for /bin/login
  76. */
  77. VT_Start_utmp()
  78. {
  79.     struct utmp    u, *v;
  80.     char        *tt;
  81.  
  82.  
  83.     setutent();
  84.  
  85.     strcpy(u.ut_line, VT_Line);
  86.  
  87.     if((v = getutline(&u)) == NULL) {
  88.         if(strncmp(VT_Line, "tty", 3) == 0)
  89.             tt = VT_Line + 3;
  90.         else if(strlen(VT_Line) > 4)
  91.             tt = VT_Line + strlen(VT_Line) - 4;
  92.         else
  93.             tt = VT_Line;
  94.  
  95.         strcpy(u.ut_id, tt);
  96.         u.ut_time = time((time_t*)0);
  97.     }
  98.  
  99.     strcpy(u.ut_user, "LOGIN");
  100.     strcpy(u.ut_line, VT_Line);
  101.     u.ut_pid = getpid();
  102.     u.ut_type = LOGIN_PROCESS;
  103.     pututline(&u);
  104.  
  105.     endutent();
  106.  
  107.     return(0);
  108. }
  109.  
  110.  
  111. /*
  112. VT_Stop_utmp: prepare /etc/utmp for other processes
  113. */
  114. VT_Stop_utmp()
  115. {
  116.     struct utmp    u, *v;
  117.  
  118.  
  119.     if(VT_Line != NULL) {
  120.         setutent();
  121.  
  122.         strcpy(u.ut_line, VT_Line);
  123.  
  124.         if((v = getutline(&u)) != NULL) {
  125.             strcpy(v->ut_user, "");
  126.             v->ut_type = DEAD_PROCESS;
  127.             v->ut_time = time((time_t*)0);
  128.             pututline(v);
  129.         }
  130.  
  131.         endutent();
  132.     }
  133.  
  134.     return(0);
  135. }
  136.  
  137.  
  138. /*
  139. VT_AtExit: Things to do when the program exits
  140. */
  141. void    VT_AtExit()
  142. {
  143.     if(VT_ChildPID > 0) {
  144.         kill(VT_ChildPID, SIGHUP);
  145.         (void)wait(NULL);
  146.     }
  147.  
  148.     VT_Stop_utmp();
  149. }
  150.  
  151.  
  152. /*
  153. VT_SigCLD: signalhandler for SIGCLD: set flag if child-process died
  154. */
  155. void    VT_SigCLD(sig)
  156. int    sig;
  157. {
  158.     if(wait(NULL) == VT_ChildPID)
  159.         VT_ChildDied = True;
  160.     else
  161.         signal(SIGCLD, VT_SigCLD);
  162. }
  163.  
  164.  
  165. /*
  166. VT_SigEXIT: signalhandler for signals that cause the process to exit
  167. */
  168. void    VT_SigEXIT(sig)
  169. int    sig;
  170. {
  171.     VT_AtExit();
  172.  
  173.     exit(1);
  174. }
  175.  
  176.  
  177. /*
  178. VT_Start: initialize vt-specific data, alloc pty, spawn shell and send ACK
  179. */
  180. int    VT_Start()
  181. {
  182.     char    OutBuf [64], *X, *Y;
  183.  
  184.  
  185.     ms_type = MS_NONE;
  186.     master = slave = -1;
  187.  
  188. #ifdef HAS_VTY
  189. #ifdef LINUX
  190. #    define    MASTER_TMPL    "/dev/pty  "
  191. #    define    SLAVE_TMPL    "/dev/tty  "
  192. #    define    LETTER1        "pqrs"
  193. #    define    POS1        8
  194. #    define    LETTER2        "0123456789abcdef"
  195. #    define    POS2        9
  196. #endif
  197.  
  198. #ifdef SCO
  199. #    define    MASTER_TMPL    "/dev/ptyp_  "
  200. #    define    SLAVE_TMPL    "/dev/ttyp_  "
  201. #    define    LETTER1        "0123456"
  202. #    define    POS1        10
  203. #    define    LETTER2        "0123456789abcdef"
  204. #    define    POS2        11
  205. #endif
  206.  
  207.     if(ms_poll == MS_VTY || ms_poll == 0) {
  208.         strcpy(master_name, MASTER_TMPL);
  209.         strcpy(slave_name, SLAVE_TMPL);
  210.  
  211.         for(X = LETTER1; *X && master < 0; X++)
  212.             for(Y = LETTER2; *Y && master < 0; Y++) {
  213.                 master_name [POS1] = *X;
  214.                 master_name [POS2] = *Y;
  215.                 if((master = open(master_name, O_RDWR)) >= 0) {
  216.                     slave_name [POS1] = *X;
  217.                     slave_name [POS2] = *Y;
  218.                     if((slave = open(slave_name, O_RDWR)) < 0)
  219.                         close(master);
  220.                 }
  221.             }
  222.  
  223.         if(master >= 0 && slave >= 0)
  224.             ms_type = MS_VTY;
  225.     }
  226.  
  227. #    undef    MASTER_TMPL
  228. #    undef    SLAVE_TMPL
  229. #    undef    LETTER1
  230. #    undef    LETTER2
  231. #    undef    POS1
  232. #    undef    POS2
  233. #endif
  234.  
  235.  
  236. #ifdef HAS_PTY
  237. #ifdef SCO
  238. #    define    MASTER_TMPL    "/dev/ptyp%d"
  239. #    define    SLAVE_TMPL    "/dev/ttyp%d"
  240. #    define    MIN_I        0
  241. #    define    MAX_I        63
  242. #endif
  243.  
  244.     if(ms_poll == MS_PTY || ms_poll == 0) {
  245.         int    i;
  246.  
  247.         for(i = MIN_I; i <= MAX_I && master < 0; i++) {
  248.             sprintf(master_name, MASTER_TMPL, i);
  249.             if((master = open(master_name, O_RDWR)) >= 0) {
  250.                 sprintf(slave_name, SLAVE_TMPL, i);
  251.                 if((slave = open(slave_name, O_RDWR)) < 0)
  252.                     close(master);
  253.             }
  254.         }
  255.  
  256.         if(master >= 0 && slave >= 0)
  257.             ms_type = MS_PTY;
  258.     }
  259.  
  260. #    undef    MASTER_TMPL
  261. #    undef    SLAVE_TMPL
  262. #    undef    MIN_I
  263. #    undef    MAX_I
  264. #endif
  265.  
  266.  
  267.     if(! ms_type)
  268.         return(-1);
  269.  
  270.     VT_Line = strdup(strrchr(slave_name, '/') + 1);
  271.  
  272.     switch((VT_ChildPID = fork())) {
  273.     case -1:
  274.         return(-1);
  275.         break;
  276.  
  277.     case 0:
  278. #ifdef SCO
  279.         setsid();
  280. #endif
  281.         close(0);
  282.         close(1);
  283.         close(2);
  284.  
  285.         i = open(slave_name, O_RDWR);
  286.         o = open(slave_name, O_RDWR);
  287.         e = open(slave_name, O_RDWR);
  288.  
  289. #ifdef LINUX
  290.         setsid();
  291.         if (ioctl(slave, TIOCSCTTY, (char *)NULL) == -1)
  292.             exit(1);
  293. #endif
  294. #ifdef SCO
  295.         tcsetpgrp(0, getpid());
  296. #endif
  297.  
  298.         VT_Start_utmp();
  299.  
  300.         system("stty sane");
  301.         execlp("/bin/login", "login", "-c", (char*)0);
  302.         exit(1);
  303.         break;
  304.  
  305.     default:
  306.         VT_Mode = True;
  307.         VT_Status = VT_OPEN;
  308.         VT_ChildDied = False;
  309.         VT_Fd = master;
  310.  
  311.         signal(SIGCLD, VT_SigCLD);
  312.  
  313.         signal(SIGHUP, VT_SigEXIT);
  314.         signal(SIGTERM, VT_SigEXIT);
  315.         signal(SIGINT, VT_SigEXIT);
  316.         signal(SIGQUIT, VT_SigEXIT);
  317.  
  318.         memset(OutBuf, 0, sizeof(OutBuf));
  319.         OutBuf [4] = 0x06;
  320.         _smb_setlen(OutBuf, 1);
  321.  
  322.         send_smb(Client,OutBuf);
  323.  
  324.         return(0);
  325.         break;
  326.     }
  327. }
  328.  
  329.  
  330. /*
  331. VT_Output: transport data from socket to pty
  332. */
  333. int    VT_Output(Buffer)
  334. char    *Buffer;
  335. {
  336.     int        i, len, nb;
  337.  
  338.  
  339.     if(VT_Status != VT_OPEN)
  340.         return(-1);
  341.  
  342.     len = smb_len(Buffer);
  343.  
  344.     nb = write(VT_Fd, Buffer + 4, len);
  345.  
  346.     return((nb == len) ? 0 : -1);
  347. }
  348.  
  349.  
  350. /*
  351. VT_Input: transport data from pty to socket
  352. */
  353. int    VT_Input(Buffer, Size)
  354. char    *Buffer;
  355. int        Size;
  356. {
  357.     int        len;
  358.  
  359.  
  360.     if(VT_Status != VT_OPEN)
  361.         return(-1);
  362.  
  363.     memset(Buffer, 0, Size);
  364.     len = read(VT_Fd, Buffer + 4, MIN(VT_MAXREAD, Size));
  365.  
  366.     _smb_setlen(Buffer, len);
  367.  
  368.     return(len + 4);
  369. }
  370.  
  371.  
  372. /*
  373. VT_Process: main loop while in vt-mode
  374. */
  375. void VT_Process()
  376. {
  377.     static int    trans_num = 0;
  378.     extern int    Client;
  379.     int            nread;
  380.  
  381.  
  382.     VT_Start();
  383.  
  384.     atexit(VT_AtExit);
  385.  
  386.     while (True) {
  387.         int32            len;      
  388.         int                msg_type;
  389.         int                msg_flags;
  390.         int                counter;
  391.         int                last_keepalive=0;
  392.         struct fd_set    si;
  393.         struct timeval    to, *top;
  394.         int                n, ret, t;
  395.  
  396.  
  397.         errno = 0;
  398.         t = SMBD_SELECT_LOOP*1000;
  399.  
  400.  
  401.         FD_ZERO(&si);
  402.         FD_SET(Client, &si);
  403.  
  404.         FD_SET(VT_Fd, &si);
  405.  
  406.         if(t >= 0) {
  407.             to.tv_sec = t / 1000;
  408.             to.tv_usec = t - (to.tv_sec * 1000);
  409.  
  410.             top = &to;
  411.         } else
  412.             top = NULL;
  413.  
  414.         if(VT_ChildDied)
  415.             goto leave_VT_Process;
  416.  
  417.         n = select(MAX(VT_Fd, Client) + 1, &si, NULL, NULL, top);
  418.  
  419.         if(VT_ChildDied)
  420.             goto leave_VT_Process;
  421.     
  422.         if(n == 0) {
  423.             int i;
  424.             time_t t;
  425.             BOOL allidle = True;
  426.             extern int keepalive;
  427.     
  428.             counter += SMBD_SELECT_LOOP;
  429.  
  430.             t = time(NULL);
  431.     
  432.             if (keepalive && (counter-last_keepalive)>keepalive) {
  433.                 if (!send_keepalive(Client))
  434.                     goto leave_VT_Process;
  435.                 last_keepalive = counter;
  436.             }
  437.         } else if(n > 0) {
  438.             counter = 0;
  439.  
  440.             if(FD_ISSET(VT_Fd, &si)) {
  441.                 /* got input from vt */
  442.                 nread = VT_Input(OutBuffer, MIN(BUFFER_SIZE,lp_maxxmit()));
  443.  
  444.                 if(nread > 0)
  445.                     send_smb(Client,OutBuffer);
  446.             }
  447.  
  448.             if(FD_ISSET(Client, &si)) {
  449.                 /* got input from socket */
  450.  
  451.                 if(receive_smb(Client,InBuffer, 0)) {
  452.                     msg_type = CVAL(InBuffer,0);
  453.                     msg_flags = CVAL(InBuffer,1);
  454.     
  455.                     len = smb_len(InBuffer);
  456.     
  457.                     DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
  458.     
  459.                     nread = len + 4;
  460.           
  461.                     DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
  462.     
  463.                     if(msg_type == 0)
  464.                         VT_Output(InBuffer);
  465.                     else {
  466.                         nread = construct_reply(InBuffer,OutBuffer,nread,MIN(BUFFER_SIZE,lp_maxxmit()));
  467.          
  468.                         if(nread > 0) {
  469.                             if (nread != smb_len(OutBuffer) + 4) {
  470.                                 DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
  471.                                     nread,
  472.                                     smb_len(OutBuffer)));
  473.                             } else
  474.                                 send_smb(Client,OutBuffer);
  475.                         }
  476.                     }
  477.                 } else
  478.                     if(errno == EBADF)
  479.                         goto leave_VT_Process;
  480.             }
  481.         }
  482.  
  483.         trans_num++;
  484.     }
  485.  
  486.     leave_VT_Process:
  487. /*
  488.         if(VT_ChildPID > 0)
  489.             kill(VT_ChildPID, SIGHUP);
  490.  
  491.         VT_Stop_utmp(VT_Line);
  492.         return;
  493. */
  494.         close_sockets();
  495.         exit(0);
  496. }
  497.